#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <dirent.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <syslog.h>
#include "cJSON.h"
//#include "mosquitto_arg.h"
#include "mosquitto.h"
int g_stop = 0;


typedef struct mosquitto_s 
{
    char               *host;
    int                port;
    char               *topic;
    char               *client_id;
    char               *user;
    char               *password;
    int                keepalive;
    char               *recv_message;
    char               *send_message;
}mosquitto_t;


char            timechar[256]={0};


void sig_handle(int signum)
{
        if(SIGUSR1 == signum)
        {
                g_stop = 1;
        }
}
void print_usage(char *progname)
{
        printf("%s usage: \n",progname);
        printf("-H(--broker addr):specify Aliyun  address.\n");
        printf("-p(--port):specify server Aliyun port.\n");
        printf("-t(--topic): have publish power topic\n");
        printf("-d(--daemon):\n");
        printf("-c(--client_id): put Aliyun clinet id\n");
        printf("-u(--user): put Aliyun usr name\n");
        printf("-s(--passwd): put usr passwd\n");
        printf("-k(--keepalive): put keep time\n");
        printf("-h(--help): print this help information\n");
}

int ds18b20_get_temperature(double *temp);

char *get_date_time(char *datetime);

void pub_connect_callback(struct mosquitto *mosqut, void *obj, int rc);

int mosquitto_pub_start(struct mosquitto* mosqut,mosquitto_t* mosquittio);

int main(int argc,char **argv)
{
        int             daemon_run = 0;
        int             opt;
        int             rv = -1;
        mosquitto_t     mosq;

        struct mosquitto* mosqut;

        memset(&mosq,0,sizeof(mosq));

        struct option           opts[] = { 
                {"Host",required_argument,NULL,'H'},
                {"port",required_argument,NULL,'p'},
                {"topic",required_argument,NULL,'t'},
                {"daemon",no_argument,NULL,'d'},
                {"client_id",required_argument,NULL,'c'},
                {"user name",required_argument,NULL,'u'},
                {"Passwd",required_argument,NULL,'s'},
                {"keepalive",required_argument,NULL,'k'},
                {"help",no_argument,NULL,'h'},

                {NULL,0,NULL,0}
        };  

        while((opt = getopt_long(argc,argv,"H:p:t:dc:u:s:k:h",opts,NULL)) != -1) 
        {   
                switch(opt)
                {   
                        case 'H':
                                mosq.host = optarg;
                                break;
                        case 'p':
                                mosq.port = atoi(optarg);
                                break;
                        case 't':
                                mosq.topic = optarg;
                                break;
                        case 'd':
                                daemon_run = 1;
                                break;
                        case 'c':
                                mosq.client_id = optarg;
                                break;
                        case 'u':
                                mosq.user = optarg;
                                break;
                        case 's':
                                mosq.password = optarg;
                                break;
                        case 'k':
                                mosq.keepalive = atoi(optarg);
                                break;
                        case 'h':
                                print_usage(argv[0]);
                                return 0;


                }   
        }

        mosq.send_message = NULL;
        mosq.recv_message = NULL;


        if (mosq.host == NULL||!mosq.port||mosq.topic == NULL||mosq.client_id == NULL||\
          mosq.user == NULL||mosq.password == NULL||!mosq.keepalive )
        {
                print_usage(argv[0]);

                return 0;
        }
        if(daemon_run)
        {
                daemon(0,0);
        }
        signal(SIGUSR1,sig_handle);
        rv = mosquitto_pub_start(mosqut,&mosq);



        return 0;

}

char * get_date_time(char *datetime)
{
        struct tm       *timenow;
        time_t          second=time(0);
        timenow = localtime(&second);
        sprintf(timechar,"%d-%d-%d %d:%d:%d",timenow->tm_year+1900,timenow->tm_mon+1,\
        timenow->tm_mday,timenow->tm_hour,timenow->tm_min,timenow->tm_sec);
        datetime = timechar;
        return datetime;



}
int ds18b20_get_temperature(double *temp)
{
        char    w1_path[50] = "/sys/bus/w1/devices/";
        char    chip[20];
        char    buf[128];
        DIR     *dirp;
        struct dirent   *direntp;
        int     fd = -1; 
        char    *ptr;
        float   value;
        int     found = 0;


        if( !temp )
        {   
    
                return -1; 
        }    

        if(( dirp = opendir(w1_path)) == NULL)
        {   
                printf("Open dir error: %s\n",strerror(errno));
                return -2;
        }

        while((direntp = readdir(dirp)) != NULL)
        {
                if(strstr(direntp->d_name,"28-"))
                {
                        strcpy(chip,direntp->d_name);
                        found = 1;
                }
        }
        closedir(dirp);

        if( !found )
        {
                printf("Can not find ds18b20 in %S\n",w1_path);
                return -4;
        }

        strncat(w1_path,chip,sizeof(chip)-1);
        strcat(w1_path,"/w1_slave");

        if( (fd=open(w1_path,O_RDONLY))<0 )
        {
                printf("Open %s error: %s\n",w1_path,strerror(errno));
                return -4;
        }

        if( read(fd,buf,sizeof(buf))<0 )
        {
                printf("read %s error: %s\n",w1_path,strerror(errno));
                return -5;
        }

        ptr = strstr(buf,"t=")+2;

        if( !ptr )
        {
                printf("ERROR:Can not get temperature\n");
                return -6;
        }

        *temp = atof(ptr)/1000;
        return 0;
}

int mosquitto_pub_start(struct mosquitto* mosqut,mosquitto_t *mosq)
{
        int rv = -1;
        rv =  mosquitto_lib_init();

        if(rv != MOSQ_ERR_SUCCESS )
        {
                printf("Init mosquitto lib failure: %s\n",strerror(errno));
                goto cleanup;
        }

        mosqut = mosquitto_new(mosq->client_id,false,(void*)mosq);
        if(!mosqut)
        {
                printf("Creat mosquitto client failure: %s\n",strerror(errno));
                goto cleanup;
        }

        printf("Creat mosquitto client success\n");


        mosquitto_connect_callback_set(mosqut,pub_connect_callback);

        if(mosquitto_username_pw_set(mosqut,mosq->user,mosq->password))
        {
                printf("mosquitto username and passwd failure: %s\n",strerror(errno));
                goto cleanup;
        }


        while(!g_stop)
        {
                rv = mosquitto_connect(mosqut,mosq->host,mosq->port,mosq->keepalive);

                if(rv != MOSQ_ERR_SUCCESS)
                {
                        printf("Client connnect to Server failure: %s\n",strerror(errno));
                        continue;
                        sleep(1);
                }

                printf("Connect to Aliyun success\n");

                rv = mosquitto_loop_forever(mosqut,-1,1);

                sleep(30);



                if(rv!=MOSQ_ERR_SUCCESS)
                {
                        printf("%s\n",strerror(errno));
                        goto cleanup;
                }
                printf("MOS_pub_start success\n");
        }


        printf("pub_close\n");
        return 0;

cleanup:
        printf("pub_satrt failure!!\n");

        mosquitto_destroy(mosqut);
        mosquitto_lib_cleanup();
        return 0;



}

void pub_connect_callback(struct mosquitto *mosqut, void *obj, int rc)
{
        cJSON*          cjson_msg = NULL;
        cJSON*          cjson_properties = NULL;
        char*           str;
        double          temp;
        char            *datetime;
        char            *id = "JMQ";
        int             mid;
        mosquitto_t     *mosq;
        mosq = (mosquitto_t*)obj;

        if( ds18b20_get_temperature(&temp) < 0 )
        {
            printf("get temp failuer\n");
        }

        printf("get temp: %f摄氏度\n",temp);
        datetime = get_date_time(datetime);
        printf("DATE:%s\n",datetime);

    /* 创建一个JSON数据对象(链表头结点) */
         cjson_msg = cJSON_CreateObject();

    /* 添加一个字符串类型的JSON数据 */
        cJSON_AddStringToObject(cjson_msg,"method","thing.event.property.post");

    /* 添加一个符串类型的JSON数据*/
        cJSON_AddStringToObject(cjson_msg,"id",id);
    /* 添加一个嵌套的JSON数据*/
        cJSON* cjson_params = cJSON_CreateObject();
        cJSON_AddNumberToObject(cjson_params,"CurrentTemperature",temp);
        cJSON_AddStringToObject(cjson_params,"DATE",datetime);
        cJSON_AddItemToObject(cjson_msg,"params",cjson_params);

        str = cJSON_Print(cjson_msg);
        printf("%s\n", str);

        if(rc==0)
        {
                if(mosquitto_publish(mosqut,&mid,mosq->topic,strlen(str)+1,str,0,true)!=MOSQ_ERR_SUCCESS)
                {
                        printf("Mosquitto Pub failure: %s\n",strerror(errno));
                        return;
                }

                printf("Mosquitto Pub success,PUB_TOPIC:%s\n",mosq->topic);
                printf(" rc:%d\n",rc);
        }


        mosquitto_disconnect(mosqut);
        cJSON_Delete(cjson_msg);

}
